if (openSUSE)
    # openSUSE don't install wx in a standard library system
    # path. Let's bypass the dynamic linker and hardcode the path.
    set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON)
endif()

# Check that people use the good file
if(NOT TOP_CMAKE_WAS_SOURCED)
    message(FATAL_ERROR "
    You did not 'cmake' the good CMakeLists.txt file. Use the one in the top dir.
    It is advice to delete all wrongly generated cmake stuff => CMakeFiles & CMakeCache.txt")
endif()


set(CommonFlags
    -fno-strict-aliasing
    -Wstrict-aliasing # Allow to track strict aliasing issue.
    -Wno-parentheses
    -Wno-missing-braces
    -Werror=date-time
#    -DWX_PRECOMP
	)

# Largely turning off because LegacyPluginAPI_Common in Plugins.h spams really badly in gcc 8 due to the memzero initialization.
# Should probably be fixed properly, but for now this should work.
if(GCC_VERSION VERSION_EQUAL "8.0" OR GCC_VERSION VERSION_GREATER "8.0")
    set(CommonFlags
	    ${CommonFlags}
	    -Wno-class-memaccess
    )
endif()



if ("${PGO}" STREQUAL "generate")
    set(pcsx2FinalFlags -fprofile-generate)
elseif("${PGO}" STREQUAL "use")
    set(pcsx2FinalFlags -fprofile-use)
else()
    set(pcsx2FinalFlags "")
endif()

set(pcsx2FinalFlags ${pcsx2FinalFlags} "-DSPU2X_PORTAUDIO" ${CommonFlags})

if(XDG_STD)
    set(pcsx2FinalFlags ${pcsx2FinalFlags} -DXDG_STD)
endif()

if(LIBRETRO)
   set(Output pcsx2_libretro)
else()
   set(Output PCSX2)
endif()

# Main pcsx2 source
set(pcsx2Sources
	Cache.cpp
	COP0.cpp
	COP2.cpp
	Counters.cpp
	GameDatabase.cpp
	Dump.cpp
	Elfheader.cpp
	FW.cpp
	FiFo.cpp
	FPU.cpp
	Gif.cpp
	Gif_Logger.cpp
	Gif_Unit.cpp
	GS.cpp
	GSState.cpp
	Hw.cpp
	HwRead.cpp
	HwWrite.cpp
	Interpreter.cpp
	IopBios.cpp
	IopCounters.cpp
	IopDma.cpp
	IopGte.cpp
	IopHw.cpp
	IopIrq.cpp
	IopMem.cpp
	IopSio2.cpp
	IPC.cpp
	Mdec.cpp
	Memory.cpp
	MMI.cpp
	MTGS.cpp
	MTVU.cpp
	MultipartFileReader.cpp
	OutputIsoFile.cpp
	Patch.cpp
	Patch_Memory.cpp
	Pcsx2Config.cpp
	PluginManager.cpp
	PrecompiledHeader.cpp
	R3000A.cpp
	R3000AInterpreter.cpp
	R3000AOpcodeTables.cpp
	R5900.cpp
	R5900OpcodeImpl.cpp
	R5900OpcodeTables.cpp
	SaveState.cpp
	ShiftJisToUnicode.cpp
	Sif.cpp
	Sif0.cpp
	Sif1.cpp
	sif2.cpp
	Sio.cpp
	SourceLog.cpp
	SPR.cpp
	System.cpp
	Vif0_Dma.cpp
	Vif1_Dma.cpp
	Vif1_MFIFO.cpp
	Vif.cpp
	Vif_Codes.cpp
	Vif_Transfer.cpp
	Vif_Unpack.cpp
	vtlb.cpp
	VU0.cpp
	VUmicro.cpp
	VU0micro.cpp
	VU0microInterp.cpp
	VU1micro.cpp
	VU1microInterp.cpp
	VUflags.cpp
	VUmicroMem.cpp
	VUops.cpp)

# Main pcsx2 header
set(pcsx2Headers
	AsyncFileReader.h
	Cache.h
	cheatscpp.h
	Common.h
	Config.h
	COP0.h
	Counters.h
	Dmac.h
	Dump.h
	GameDatabase.h
	Elfheader.h
	FW.h
	Gif.h
	Gif_Unit.h
	GS.h
	Hardware.h
	Hw.h
	IopBios.h
	IopCommon.h
	IopCounters.h
	IopDma.h
	IopGte.h
	IopHw.h
	IopMem.h
	IopSio2.h
	IPC.h
	Mdec.h
	MTVU.h
	Memory.h
	MemoryTypes.h
	Patch.h
	PathDefs.h
	Plugins.h
	PrecompiledHeader.h
	R3000A.h
	R5900Exceptions.h
	R5900.h
	R5900OpcodeTables.h
	SaveState.h
	Sifcmd.h
	Sif.h
	Sio.h
	sio_internal.h
	SPR.h
	SysForwardDefs.h
	System.h
	Vif_Dma.h
	Vif.h
	Vif_Unpack.h
	vtlb.h
	VUflags.h
	VUmicro.h
	VUops.h)

# CDVD sources
set(pcsx2CDVDSources
	CDVD/BlockdumpFileReader.cpp
	CDVD/CdRom.cpp
	CDVD/CDVDaccess.cpp
	CDVD/CDVD.cpp
	CDVD/CDVDdiscReader.cpp
	CDVD/CDVDisoReader.cpp
	CDVD/CDVDdiscThread.cpp
	CDVD/InputIsoFile.cpp
	CDVD/OutputIsoFile.cpp
	CDVD/ChunksCache.cpp
	CDVD/CompressedFileReader.cpp
	CDVD/CsoFileReader.cpp
	CDVD/GzippedFileReader.cpp
	CDVD/IsoFS/IsoFile.cpp
	CDVD/IsoFS/IsoFSCDVD.cpp
	CDVD/IsoFS/IsoFS.cpp
    )

# CDVD headers
set(pcsx2CDVDHeaders
	CDVD/CdRom.h
	CDVD/CDVDaccess.h
	CDVD/CDVD.h
	CDVD/CDVD_internal.h
	CDVD/CDVDdiscReader.h
	CDVD/CDVDisoReader.h
	CDVD/ChunksCache.h
	CDVD/CompressedFileReader.h
	CDVD/CompressedFileReaderUtils.h
	CDVD/CsoFileReader.h
	CDVD/GzippedFileReader.h
	CDVD/IsoFileFormats.h
	CDVD/IsoFS/IsoDirectory.h
	CDVD/IsoFS/IsoFileDescriptor.h
	CDVD/IsoFS/IsoFile.h
	CDVD/IsoFS/IsoFSCDVD.h
	CDVD/IsoFS/IsoFS.h
	CDVD/IsoFS/SectorSource.h
	CDVD/zlib_indexed.h
	)
if(LIBRETRO)
	# SPU2 sources
	set(pcsx2SPU2Sources
		SPU2/ADSR.cpp
		SPU2/Debug.cpp
		SPU2/DplIIdecoder.cpp
		SPU2/Dma.cpp
		SPU2/Lowpass.cpp
		SPU2/Mixer.cpp
		SPU2/spu2.cpp
		SPU2/ReadInput.cpp
		SPU2/RegLog.cpp
		SPU2/RegTable.cpp
		SPU2/Reverb.cpp
#		SPU2/SndOut.cpp
#		SPU2/SndOut_SDL.cpp
#		SPU2/SndOut_Portaudio.cpp
		SPU2/spu2freeze.cpp
		SPU2/spu2replay.cpp
		SPU2/spu2sys.cpp
#		SPU2/Timestretcher.cpp
#     SPU2/Wavedump_wav.cpp
#     SPU2/WavFile.cpp
#		SPU2/wx/wxConfig.cpp
		 )
       if(MSVC)
          set(pcsx2SPU2Sources ${pcsx2SPU2Sources}
             SPU2/Windows/RealtimeDebugger.cpp
             SPU2/Windows/ConfigDebug.cpp
             SPU2/Windows/CfgHelpers.cpp
             )
       else()
          set(pcsx2SPU2Sources ${pcsx2SPU2Sources}
       #		SPU2/Linux/Alsa.cpp
             SPU2/Linux/CfgHelpers.cpp
       #		SPU2/Linux/Config.cpp
             SPU2/Linux/ConfigDebug.cpp
       #		SPU2/Linux/ConfigSoundTouch.cpp
       #		SPU2/Linux/Dialogs.cpp
          )
       endif()

else()
	# SPU2 sources
	set(pcsx2SPU2Sources
		SPU2/ADSR.cpp
		SPU2/Debug.cpp
		SPU2/DplIIdecoder.cpp
		SPU2/Dma.cpp
		SPU2/Lowpass.cpp
		SPU2/Mixer.cpp
		SPU2/spu2.cpp
		SPU2/ReadInput.cpp
		SPU2/RegLog.cpp
		SPU2/RegTable.cpp
		SPU2/Reverb.cpp
		SPU2/SndOut.cpp
		SPU2/SndOut_SDL.cpp
		SPU2/SndOut_Portaudio.cpp
		SPU2/spu2freeze.cpp
		SPU2/spu2replay.cpp
		SPU2/spu2sys.cpp
		SPU2/Timestretcher.cpp
		SPU2/Wavedump_wav.cpp
		SPU2/WavFile.cpp
		SPU2/Linux/Alsa.cpp
		SPU2/Linux/CfgHelpers.cpp
		SPU2/Linux/Config.cpp
		SPU2/Linux/ConfigDebug.cpp
		SPU2/Linux/ConfigSoundTouch.cpp
		SPU2/Linux/Dialogs.cpp
		SPU2/wx/wxConfig.cpp
		 )
endif()

# SPU2 headers
set(pcsx2SPU2Headers
	SPU2/Config.h
	SPU2/Debug.h
	SPU2/defs.h
	SPU2/Dma.h
	SPU2/Global.h
	SPU2/Lowpass.h
	SPU2/Mixer.h
	SPU2/spu2.h
	SPU2/regs.h
	SPU2/SndOut.h
	SPU2/spdif.h
	SPU2/spu2replay.h
	SPU2/WavFile.h
	SPU2/Linux/Alsa.h
	SPU2/Linux/Config.h
	SPU2/Linux/Dialogs.h
	SPU2/wx/wxConfig.h
)

# DebugTools sources
set(pcsx2DebugToolsSources
	DebugTools/DebugInterface.cpp
	DebugTools/DisassemblyManager.cpp
	DebugTools/ExpressionParser.cpp
	DebugTools/MIPSAnalyst.cpp
	DebugTools/MipsAssembler.cpp
	DebugTools/MipsAssemblerTables.cpp
	DebugTools/MipsStackWalk.cpp
	DebugTools/Breakpoints.cpp
	DebugTools/SymbolMap.cpp
	DebugTools/DisR3000A.cpp
	DebugTools/DisR5900asm.cpp
	DebugTools/DisVU0Micro.cpp
	DebugTools/DisVU1Micro.cpp
	DebugTools/BiosDebugData.cpp)

# DebugTools headers
set(pcsx2DebugToolsHeaders
	DebugTools/DebugInterface.h
	DebugTools/DisassemblyManager.h
	DebugTools/ExpressionParser.h
	DebugTools/MIPSAnalyst.h
	DebugTools/MipsAssembler.h
	DebugTools/MipsAssemblerTables.h
	DebugTools/MipsStackWalk.h
	DebugTools/Breakpoints.h
	DebugTools/SymbolMap.h
	DebugTools/Debug.h
	DebugTools/DisASM.h
	DebugTools/DisVUmicro.h
	DebugTools/DisVUops.h
	DebugTools/BiosDebugData.h)

if(LIBRETRO)
	# gui sources
	set(pcsx2GuiSources
		gui-libretro/AppAssert.cpp
		gui-libretro/AppConfig.cpp
		gui-libretro/AppCorePlugins.cpp
		gui-libretro/AppCoreThread.cpp
		gui-libretro/AppEventSources.cpp
		gui-libretro/AppGameDatabase.cpp
		gui-libretro/AppUserMode.cpp
		gui-libretro/AppInit.cpp
		gui-libretro/AppMain.cpp
		gui-libretro/AppRes.cpp
		gui-libretro/ConsoleLogger.cpp
		gui-libretro/ExecutorThread.cpp
		gui-libretro/MemoryCardFile.cpp
		gui-libretro/MemoryCardFolder.cpp
		)
	# gui headers
	set(pcsx2GuiHeaders
		gui-libretro/AppCommon.h
		gui-libretro/AppConfig.h
		gui-libretro/AppCorePlugins.h
		gui-libretro/AppCoreThread.h
		gui-libretro/AppEventListeners.h
		gui-libretro/AppForwardDefs.h
		gui-libretro/AppGameDatabase.h
		gui-libretro/App.h
		gui-libretro/AppSaveStates.h
		gui-libretro/ConsoleLogger.h
		gui-libretro/DriveList.h
		gui-libretro/MemoryCardFile.h
		gui-libretro/MemoryCardFolder.h
		gui-libretro/pxEventThread.h
		gui-libretro/Saveslots.h
		)
else()
	# gui sources
	set(pcsx2GuiSources
		gui/AppAssert.cpp
		gui/AppConfig.cpp
		gui/AppCorePlugins.cpp
		gui/AppCoreThread.cpp
		gui/AppEventSources.cpp
		gui/AppGameDatabase.cpp
		gui/AppUserMode.cpp
		gui/AppInit.cpp
		gui/AppMain.cpp
		gui/AppRes.cpp
		gui/ConsoleLogger.cpp
		gui/CpuUsageProvider.cpp
		gui/Dialogs/AboutBoxDialog.cpp
		gui/Dialogs/AssertionDialog.cpp
		gui/Dialogs/BaseConfigurationDialog.cpp
		gui/Dialogs/ConfirmationDialogs.cpp
		gui/Dialogs/ConvertMemoryCardDialog.cpp
		gui/Dialogs/CreateMemoryCardDialog.cpp
		gui/Dialogs/FirstTimeWizard.cpp
		gui/Dialogs/ImportSettingsDialog.cpp
		gui/Dialogs/LogOptionsDialog.cpp
		gui/Dialogs/McdConfigDialog.cpp
		gui/Dialogs/PickUserModeDialog.cpp
		gui/Dialogs/SysConfigDialog.cpp
		gui/Debugger/BreakpointWindow.cpp
		gui/Debugger/CtrlDisassemblyView.cpp
		gui/Debugger/CtrlRegisterList.cpp
		gui/Debugger/CtrlMemView.cpp
		gui/Debugger/DebuggerLists.cpp
		gui/Debugger/DisassemblyDialog.cpp
		gui/Debugger/DebugEvents.cpp
		gui/DriveList.cpp
		gui/ExecutorThread.cpp
		gui/FrameForGS.cpp
		gui/GlobalCommands.cpp
		gui/i18n.cpp
		gui/IsoDropTarget.cpp
		gui/MainFrame.cpp
		gui/MainMenuClicks.cpp
		gui/MemoryCardFile.cpp
		gui/MemoryCardFolder.cpp
		gui/MessageBoxes.cpp
		gui/MSWstuff.cpp
		gui/Panels/BaseApplicableConfigPanel.cpp
		gui/Panels/BiosSelectorPanel.cpp
		gui/Panels/CpuPanel.cpp
		gui/Panels/DirPickerPanel.cpp
		gui/Panels/GameFixesPanel.cpp
		gui/Panels/GSWindowPanel.cpp
		gui/Panels/LogOptionsPanels.cpp
		gui/Panels/MemoryCardListPanel.cpp
		gui/Panels/MemoryCardListView.cpp
		gui/Panels/MiscPanelStuff.cpp
		gui/Panels/PathsPanel.cpp
		gui/Panels/PluginSelectorPanel.cpp
		gui/Panels/SpeedhacksPanel.cpp
		gui/Panels/VideoPanel.cpp
		gui/RecentIsoList.cpp
		gui/Saveslots.cpp
		gui/SysState.cpp
		gui/UpdateUI.cpp
		)

	# gui headers
	set(pcsx2GuiHeaders
		gui/AppAccelerators.h
		gui/AppCommon.h
		gui/AppConfig.h
		gui/AppCorePlugins.h
		gui/AppCoreThread.h
		gui/AppEventListeners.h
		gui/AppForwardDefs.h
		gui/AppGameDatabase.h
		gui/App.h
		gui/ApplyState.h
		gui/AppSaveStates.h
		gui/ConsoleLogger.h
		gui/CpuUsageProvider.h
		gui/Debugger/BreakpointWindow.h
		gui/Debugger/CtrlDisassemblyView.h
		gui/Debugger/CtrlMemView.h
		gui/Debugger/CtrlRegisterList.h
		gui/Debugger/DebugEvents.h
		gui/Debugger/DebuggerLists.h
		gui/Debugger/DisassemblyDialog.h
		gui/Dialogs/BaseConfigurationDialog.inl
		gui/Dialogs/ConfigurationDialog.h
		gui/Dialogs/LogOptionsDialog.h
		gui/Dialogs/ModalPopups.h
		gui/DriveList.h
		gui/GSFrame.h
		gui/i18n.h
		gui/IsoDropTarget.h
		gui/MainFrame.h
		gui/MemoryCardFile.h
		gui/MemoryCardFolder.h
		gui/MSWstuff.h
		gui/Panels/ConfigurationPanels.h
		gui/Panels/LogOptionsPanels.h
		gui/Panels/MemoryCardPanels.h
		gui/pxEventThread.h
		gui/RecentIsoList.h
		gui/Saveslots.h
		)
endif()
if(NOT MSVC)
# Warning: the declaration of the .h are mandatory in case of resources files. It will ensure the creation
# from the bin2cpp tools at right good moment (ie .h must be created before the pcsx2 compilation)
# Gui resources headers
set(res_bin "${CMAKE_BINARY_DIR}/pcsx2/gui/Resources")
set(res_src "${CMAKE_SOURCE_DIR}/pcsx2/gui/Resources")
set(pcsx2GuiResources
    ${res_bin}/AppIcon16.h
    ${res_bin}/AppIcon32.h
    ${res_bin}/AppIcon64.h
    ${res_bin}/BackgroundLogo.h
    ${res_bin}/ButtonIcon_Camera.h
    ${res_bin}/ConfigIcon_Cpu.h
    ${res_bin}/ConfigIcon_Gamefixes.h
    ${res_bin}/ConfigIcon_MemoryCard.h
    ${res_bin}/ConfigIcon_Paths.h
    ${res_bin}/ConfigIcon_Plugins.h
    ${res_bin}/ConfigIcon_Speedhacks.h
    ${res_bin}/ConfigIcon_Video.h
    ${res_bin}/Logo.h
    ${res_bin}/Breakpoint_Active.h
    ${res_bin}/Breakpoint_Inactive.h
    )
endif()
# IPU sources
set(pcsx2IPUSources
	IPU/IPU.cpp
	IPU/IPU_Fifo.cpp
	IPU/IPUdither.cpp
	IPU/IPUdma.cpp
	IPU/mpeg2lib/Idct.cpp
	IPU/mpeg2lib/Mpeg.cpp
	IPU/yuv2rgb.cpp)

# IPU headers
set(pcsx2IPUHeaders
	IPU/IPUdma.h
	IPU/IPU_Fifo.h
	IPU/IPU.h
	IPU/mpeg2lib/Mpeg.h
	IPU/mpeg2lib/Vlc.h
	IPU/yuv2rgb.h
	)

# Linux sources
set(pcsx2LinuxSources
	CDVD/Linux/DriveUtility.cpp
	CDVD/Linux/IOCtlSrc.cpp
	Linux/LnxFlatFileReader.cpp
   )
if(NOT LIBRETRO)
   set(pcsx2LinuxSources ${pcsx2LinuxSources}
      Linux/LnxConsolePipe.cpp
      Linux/LnxKeyCodes.cpp
      gui/CpuUsageProviderLnx.cpp)
endif()

set(pcsx2OSXSources
	CDVD/Linux/DriveUtility.cpp
	CDVD/Linux/IOCtlSrc.cpp
	Darwin/DarwinFlatFileReader.cpp
	)

if(NOT LIBRETRO)
   set(pcsx2OSXSources ${pcsx2OSXSources}
      Linux/LnxConsolePipe.cpp
      #	Linux/LnxKeyCodes.cpp
      gui/CpuUsageProviderLnx.cpp)
endif()

set(pcsx2FreeBSDSources
	CDVD/Linux/DriveUtility.cpp
	CDVD/Linux/IOCtlSrc.cpp
	Darwin/DarwinFlatFileReader.cpp
	)

if(NOT LIBRETRO)
   set(pcsx2FreeBSDSources ${pcsx2FreeBSDSources}
      Linux/LnxConsolePipe.cpp
      Linux/LnxKeyCodes.cpp
      gui/CpuUsageProviderLnx.cpp)
endif()

# Linux headers
set(pcsx2LinuxHeaders
	)

# ps2 sources
set(pcsx2ps2Sources
	ps2/BiosTools.cpp
	ps2/pgif.cpp
	ps2/LegacyDmac.cpp
	ps2/Iop/IopHwRead.cpp
	ps2/Iop/IopHwWrite.cpp
	ps2/Iop/PsxBios.cpp)

# ps2 headers
set(pcsx2ps2Headers
	ps2/BiosTools.h
	ps2/eeHwTraceLog.inl
	ps2/pgif.h
	ps2/HwInternal.h
	ps2/Iop/IopHw_Internal.h)

# RDebug sources
set(pcsx2RDebugSources
	RDebug/deci2.cpp
	RDebug/deci2_dbgp.cpp
	RDebug/deci2_dcmp.cpp
	RDebug/deci2_drfp.cpp
	RDebug/deci2_iloadp.cpp
	RDebug/deci2_netmp.cpp
	RDebug/deci2_ttyp.cpp)

# RDebug headers
set(pcsx2RDebugHeaders
	RDebug/deci2_dbgp.h
	RDebug/deci2_dcmp.h
	RDebug/deci2_drfp.h
	RDebug/deci2.h
	RDebug/deci2_iloadp.h
	RDebug/deci2_netmp.h
	RDebug/deci2_ttyp.h)

# Recording sources
set(rec_src "Recording")
set(rec_vp_src "${rec_src}/VirtualPad")
set(pcsx2RecordingSources
	${rec_src}/InputRecording.cpp
	${rec_src}/InputRecordingControls.cpp
	${rec_src}/InputRecordingFile.cpp
	${rec_src}/NewRecordingFrame.cpp
	${rec_src}/PadData.cpp
	${rec_vp_src}/VirtualPad.cpp
	${rec_vp_src}/VirtualPadData.cpp
	${rec_vp_src}/VirtualPadResources.cpp
)

# Recording headers
set(pcsx2RecordingHeaders
	${rec_src}/InputRecording.h
	${rec_src}/InputRecordingControls.h
	${rec_src}/InputRecordingFile.h
	${rec_src}/NewRecordingFrame.h
	${rec_src}/PadData.h
	${rec_vp_src}/VirtualPad.h
	${rec_vp_src}/VirtualPadData.h
	${rec_vp_src}/VirtualPadResources.h
)

# Warning: the declaration of the .h are mandatory in case of resources files. It will ensure the creation
# from the bin2cpp tools at the right moment (ie .h must be created before the pcsx2 compilation)
# Recording - VirtualPad resources headers
set(res_rec_vp_src "${CMAKE_SOURCE_DIR}/pcsx2/Recording/VirtualPad/img")
set(pcsx2RecordingVirtualPadResources
	${res_rec_vp_src}/circlePressed.h
	${res_rec_vp_src}/controllerFull.h
	${res_rec_vp_src}/controllerHalf.h
	${res_rec_vp_src}/controllerThreeQuarters.h
	${res_rec_vp_src}/crossPressed.h
	${res_rec_vp_src}/downPressed.h
	${res_rec_vp_src}/l1Pressed.h
	${res_rec_vp_src}/l2Pressed.h
	${res_rec_vp_src}/l3Pressed.h
	${res_rec_vp_src}/leftPressed.h
	${res_rec_vp_src}/r1Pressed.h
	${res_rec_vp_src}/r2Pressed.h
	${res_rec_vp_src}/r3Pressed.h
	${res_rec_vp_src}/rightPressed.h
	${res_rec_vp_src}/selectPressed.h
	${res_rec_vp_src}/squarePressed.h
	${res_rec_vp_src}/startPressed.h
	${res_rec_vp_src}/trianglePressed.h
	${res_rec_vp_src}/upPressed.h
)

# System sources
set(pcsx2SystemSources
	System/SysCoreThread.cpp
	System/SysThreadBase.cpp
	System/SysFakeThread.cpp)

# System headers
set(pcsx2SystemHeaders
	System/RecTypes.h
	System/SysThreads.h)

# Utilities sources
set(pcsx2UtilitiesSources
	Utilities/FileUtils.cpp)

# Utilities headers
set(pcsx2UtilitiesHeaders
	Utilities/AsciiFile.h)

# Zip tools utilies sources
set(pcsx2ZipToolsSources
    ZipTools/thread_gzip.cpp
    ZipTools/thread_lzma.cpp)

# Zip tools utilies headers
set(pcsx2ZipToolsHeaders
    ZipTools/ThreadedZipTools.h)


# Windows sources
set(pcsx2WindowsSources
	CDVD/Windows/DriveUtility.cpp
	CDVD/Windows/IOCtlSrc.cpp
	windows/FlatFileReaderWindows.cpp
	windows/Optimus.cpp
	windows/VCprojects/IopSif.cpp
	windows/WinCompressNTFS.cpp
	windows/WinKeyCodes.cpp
	)
if(NOT LIBRETRO)
   set(pcsx2WindowsSources ${pcsx2WindowsSources}
      windows/PatchBrowser.cpp
      windows/WinConsolePipe.cpp
      gui/CpuUsageProviderMSW.cpp
   	)
endif()
# Windows headers
set(pcsx2WindowsHeaders
	windows/resource.h
	windows/Win32.h)

# x86 sources
set(pcsx2x86Sources
	x86/BaseblockEx.cpp
	x86/iCOP0.cpp
	x86/iCore.cpp
	x86/iFPU.cpp
	x86/iFPUd.cpp
	x86/iMisc.cpp
	x86/iMMI.cpp
	x86/iR3000A.cpp
	x86/iR3000Atables.cpp
	x86/iR5900Misc.cpp
	x86/ir5900tables.cpp
	x86/ix86-32/iCore-32.cpp
	x86/ix86-32/iR5900-32.cpp
	x86/ix86-32/iR5900Arit.cpp
	x86/ix86-32/iR5900AritImm.cpp
	x86/ix86-32/iR5900Branch.cpp
	x86/ix86-32/iR5900Jump.cpp
	x86/ix86-32/iR5900LoadStore.cpp
	x86/ix86-32/iR5900Move.cpp
	x86/ix86-32/iR5900MultDiv.cpp
	x86/ix86-32/iR5900Shift.cpp
	x86/ix86-32/iR5900Templates.cpp
	x86/ix86-32/recVTLB.cpp
	x86/newVif_Dynarec.cpp
	x86/newVif_Unpack.cpp
	x86/newVif_UnpackSSE.cpp
	)

# x86 headers
set(pcsx2x86Headers
	x86/BaseblockEx.h
	x86/iCOP0.h
	x86/iCore.h
	x86/iFPU.h
	x86/iMMI.h
	x86/iR3000A.h
	x86/iR5900Arit.h
	x86/iR5900AritImm.h
	x86/iR5900Branch.h
	x86/iR5900.h
	x86/iR5900Jump.h
	x86/iR5900LoadStore.h
	x86/iR5900Move.h
	x86/iR5900MultDiv.h
	x86/iR5900Shift.h
	x86/microVU_Alloc.inl
	x86/microVU_Analyze.inl
	x86/microVU_Branch.inl
	x86/microVU_Clamp.inl
	x86/microVU_Compile.inl
	x86/microVU.cpp
	x86/microVU_Execute.inl
	x86/microVU_Flags.inl
	x86/microVU.h
	x86/microVU_IR.h
	x86/microVU_Log.inl
	x86/microVU_Lower.inl
	x86/microVU_Macro.inl
	x86/microVU_Misc.h
	x86/microVU_Misc.inl
	x86/microVU_Profiler.h
	x86/microVU_Tables.inl
	x86/microVU_Upper.inl
	x86/newVif.h
	x86/newVif_HashBucket.h
	x86/newVif_UnpackSSE.h
	x86/R5900_Profiler.h
	)

# common Sources
if(LIBRETRO)
	set(Common
		${pcsx2Sources}
		${pcsx2Headers}
		${pcsx2CDVDSources}
		${pcsx2CDVDHeaders}
		${pcsx2SPU2Sources}
		${pcsx2SPU2Headers}
		${pcsx2DebugToolsSources}
		${pcsx2GuiSources}
		${pcsx2GuiResources}
		${pcsx2GuiHeaders}
		${pcsx2IPUSources}
		${pcsx2IPUHeaders}
		${pcsx2ps2Sources}
		${pcsx2ps2Headers}
#		${pcsx2RecordingSources}
#		${pcsx2RecordingVirtualPadResources}
#		${pcsx2RecordingHeaders}
		${pcsx2SystemSources}
		${pcsx2SystemHeaders}
		${pcsx2UtilitiesSources}
		${pcsx2UtilitiesHeaders}
		${pcsx2x86Sources}
		${pcsx2x86Headers}
		${pcsx2ZipToolsSources}
		${pcsx2ZipToolsHeaders})
else()
	set(Common
		${pcsx2Sources}
		${pcsx2Headers}
		${pcsx2CDVDSources}
		${pcsx2CDVDHeaders}
		${pcsx2SPU2Sources}
		${pcsx2SPU2Headers}
		${pcsx2DebugToolsSources}
		${pcsx2GuiSources}
		${pcsx2GuiResources}
		${pcsx2GuiHeaders}
		${pcsx2IPUSources}
		${pcsx2IPUHeaders}
		${pcsx2ps2Sources}
		${pcsx2ps2Headers}
		${pcsx2RecordingSources}
		${pcsx2RecordingVirtualPadResources}
		${pcsx2RecordingHeaders}
		${pcsx2SystemSources}
		${pcsx2SystemHeaders}
		${pcsx2UtilitiesSources}
		${pcsx2UtilitiesHeaders}
		${pcsx2x86Sources}
		${pcsx2x86Headers}
		${pcsx2ZipToolsSources}
		${pcsx2ZipToolsHeaders})
endif()

# platform sources
# Linux
if(Linux)
	set(Platform
		${pcsx2LinuxSources}
		${pcsx2LinuxHeaders}
		)
		
	set(Platform_Libs
		${LIBUDEV_LIBRARIES}
		)
endif()

# Windows
if(Windows)
	set(Platform
		${pcsx2WindowsSources}
		${pcsx2WindowsHeaders})
endif()

# MacOSX
if(APPLE)
	set(Platform
		${pcsx2OSXSources}
		${pcsx2LinuxHeaders})
endif()

if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" OR ${CMAKE_SYSTEM_NAME} MATCHES "NetBSD")
	set(Platform
		${pcsx2FreeBSDSources}
		${pcsx2LinuxHeaders})
endif()

set(pcsx2FinalSources
	${Common}
	${Platform}
)

set(pcsx2FinalLibs
    Utilities
    x86emitter
    ${wxWidgets_LIBRARIES}
    ${GTK2_LIBRARIES}
    ${GLIB_LIBRARIES}
    ${GLIB_GIO_LIBRARIES}
    ${ZLIB_LIBRARIES}
    ${AIO_LIBRARIES}
    ${GCOV_LIBRARIES}
    ${ALSA_LIBRARIES}
    ${SOUNDTOUCH_LIBRARIES}
    ${SDL2_LIBRARIES}
    ${PORTAUDIO_LIBRARIES}
    ${Platform_Libs}
)

if(BUILTIN_GS)
    set(pcsx2FinalLibs ${pcsx2FinalLibs} GSdx)
    if(MSVC)
       set(pcsx2FinalSources ${pcsx2FinalSources} ${CMAKE_SOURCE_DIR}/plugins/GSdx/GSdx.rc)
    endif()
endif()
if(BUILTIN_PAD)
    set(pcsx2FinalLibs ${pcsx2FinalLibs} onepad)
endif()
if(BUILTIN_USB)
    set(pcsx2FinalLibs ${pcsx2FinalLibs} USBnull-0.7.0)
endif()
if(BUILTIN_DEV9)
    set(pcsx2FinalLibs ${pcsx2FinalLibs} dev9null-0.5.0)
endif()

# additonal include directories
if(NOT LIBRETRO)
include_directories(
    gui
    x86
    ${CMAKE_BINARY_DIR}/pcsx2/gui
)
else()
include_directories(
    gui-libretro
    x86
    ${CMAKE_BINARY_DIR}/pcsx2/gui-libretro
)
endif()

if(NOT MSVC)
### Generate the resources files
file(MAKE_DIRECTORY ${res_bin})

foreach(res_file IN ITEMS
        AppIcon16 AppIcon32 AppIcon64 BackgroundLogo Logo ButtonIcon_Camera
        ConfigIcon_Cpu ConfigIcon_Gamefixes ConfigIcon_MemoryCard
        ConfigIcon_Paths ConfigIcon_Plugins ConfigIcon_Speedhacks ConfigIcon_Video Breakpoint_Active Breakpoint_Inactive)
    add_custom_command(OUTPUT  "${res_bin}/${res_file}.h" COMMAND perl ${CMAKE_SOURCE_DIR}/linux_various/hex2h.pl "${res_src}/${res_file}.png" "${res_bin}/${res_file}" )
endforeach()

### Generate Recording resource files
### Drop them into the folder alongside the png files
foreach(res_file IN ITEMS
				circlePressed controllerFull controllerHalf controllerThreeQuarters crossPressed downPressed l1Pressed l2Pressed l3Pressed leftPressed
				r1Pressed r2Pressed r3Pressed rightPressed selectPressed squarePressed startPressed trianglePressed upPressed)
    add_custom_command(OUTPUT  "${res_rec_vp_src}/${res_file}.h" COMMAND perl ${CMAKE_SOURCE_DIR}/linux_various/hex2h.pl "${res_rec_vp_src}/${res_file}.png" "${res_rec_vp_src}/${res_file}" )
endforeach()
endif()

if(USE_VTUNE)
    set(pcsx2FinalLibs ${pcsx2FinalLibs} ${VTUNE_LIBRARIES})
endif()

if(MSVC)
#   include_directories(x86/ix86-32 IPU System)
   add_definitions(-D_M_X86 -D__i386__ -DTIXML_USE_STL -D_SCL_SECURE_NO_WARNINGS)
   add_definitions(-D_ARCH_64=1 -D_M_X86_64 -D__M_X86_64) #64-bit
#   add_definitions(-D_ARCH_32=1 -D_M_X86_32) #32-bit
   set(pcsx2FinalLibs ${pcsx2FinalLibs} baseclasses)
   set(pcsx2FinalLibs ${pcsx2FinalLibs} comctl32 ws2_32 shlwapi winmm rpcrt4)
endif()

if(LIBRETRO)
#   add_link_options(-fuse-ld=gold)
#   add_link_options(-Wl,--gc-sections,--print-symbol-counts,sym.log)

   add_library(${Output} SHARED
     ${CMAKE_SOURCE_DIR}/libretro/main.cpp
     ${CMAKE_SOURCE_DIR}/libretro/options.cpp
     ${CMAKE_SOURCE_DIR}/libretro/input.cpp
     ${pcsx2FinalSources}
   )
   include_directories(. ${CMAKE_SOURCE_DIR}/libretro)
#   set(LIBRARY_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
   set_target_properties(pcsx2_libretro PROPERTIES PREFIX "")

   if(CMAKE_C_COMPILER_ID MATCHES "Clang")
      set(CLANG 1)
   endif()

   if(NOT MSVC AND NOT CLANG)
      set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
   endif()

   target_link_libraries(pcsx2_libretro PRIVATE ${pcsx2FinalLibs})
   if(PACKAGE_MODE)
       install(TARGETS ${Output} DESTINATION ${BIN_DIR})
   else(PACKAGE_MODE)
       install(TARGETS ${Output} DESTINATION ${CMAKE_SOURCE_DIR}/bin)
   endif(PACKAGE_MODE)
else()
   add_pcsx2_executable(${Output} "${pcsx2FinalSources}" "${pcsx2FinalLibs}" "${pcsx2FinalFlags}")
endif()
target_compile_features(${Output} PRIVATE cxx_std_17)

#if(COMMAND target_precompile_headers)
#	message("Using precompiled headers.")
#	target_precompile_headers(${Output} PRIVATE PrecompiledHeader.h)
#endif()

if (APPLE)
	# MacOS defaults to having a maximum protection of the __DATA segment of rw (non-executable)
	# We have a bunch of page-sized arrays in bss that we use for jit
	# Obviously not being able to make those arrays executable would be a problem
	target_link_options(${Output} PRIVATE -Wl,-segprot,__DATA,rwx,rw)

	set_target_properties(${Output} PROPERTIES
		MACOSX_BUNDLE true
		MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources/Info.plist.in"
		OUTPUT_NAME PCSX2
	)

	target_sources(${Output} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources/PCSX2.icns")
	set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources/PCSX2.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)

	# If they say to skip postprocess bundle, leave the target in but make it so they have
	# to manually run it
	if (SKIP_POSTPROCESS_BUNDLE)
		set(postprocessBundleType "")
	else()
		set(postprocessBundleType ALL)
	endif()
	# Use custom_target and not custom_command so plugins can add themselves as dependencies
	add_custom_target(pcsx2-postprocess-bundle ${postprocessBundleType}
		COMMAND ${CMAKE_COMMAND} "-DPCSX2_BUNDLE_PATH=$<TARGET_FILE_DIR:${Output}>/../.."
			-P ${CMAKE_SOURCE_DIR}/cmake/Pcsx2PostprocessBundle.cmake
	)
	add_dependencies(pcsx2-postprocess-bundle ${Output})
endif()

#if(dev9ghzdrk)
#    if(PACKAGE_MODE)
#        install(CODE "execute_process(COMMAND /bin/bash -c \"echo 'Enabling networking capability on Linux...';set -x; [ -f ${BIN_DIR}/${Output} ] && sudo setcap 'CAP_NET_RAW+eip CAP_NET_ADMIN+eip' ${BIN_DIR}/${Output}; set +x\")")
#    else()
#        install(CODE "execute_process(COMMAND /bin/bash -c \"echo 'Enabling networking capability on Linux...';set -x; [ -f ${CMAKE_SOURCE_DIR}/bin/${Output} ] && sudo setcap 'CAP_NET_RAW+eip CAP_NET_ADMIN+eip' ${CMAKE_SOURCE_DIR}/bin/${Output}; set +x\")")
#    endif()
#endif()
